#include "IP6Address.h"
#include "util/Convert.h"
#include "lang/StringFormat.hpp"
#include "lang/StringBuilder.h"
#include "array/Arrays.h"
#include "lang/System.h"
#include <algorithm>

using namespace yzrilyzr_lang;
using namespace yzrilyzr_util;
using namespace yzrilyzr_array;

namespace yzrilyzr_net{

	// 静态常量定义
	//std::shared_ptr<IP6Address> IP6Address::LOCAL_HOST=IP6Address::parse("::1");
	//std::shared_ptr<IP6Address> IP6Address::ANY_ADDRESS=IP6Address::parse("::/0");

	IP6Address::IP6Address(const yzrilyzr_array::ByteArray & fromBytes){
		fromByte(fromBytes);
	}

	IP6Address::IP6Address(int32_t maskLength, int64_t msb, int64_t lsb)
		: msb(msb), lsb(lsb){
		this->maskLength=maskLength;
	}

	std::shared_ptr<IP6Address> IP6Address::parse(const String & str){
		std::shared_ptr<IP6Address> ipptr=std::make_shared<IP6Address>();
		IP6Address & ip=*ipptr;

		auto parts=str.split("/");
		String address=parts[0];
		// Handle :: shortcut
		if(address == "::"){
			ip.msb=0;
			ip.lsb=0;
		} else{
			// Split by : and handle :: expansion
			auto groups=address.split(":");
			int32_t gapPos=-1;
			for(int32_t i=0;i < groups.length;i++){
				if(groups[i].isEmpty()){
					gapPos=i;
					break;
				}
			}
			Array<String> expandedGroups(8);
			// Initialize with zeros
			for(int32_t i=0;i < 8;i++){
				expandedGroups[i]="0";
			}
			if(gapPos != -1){
				int32_t before=gapPos;
				int32_t after=groups.length - gapPos - 1;
				// Copy groups before the gap
				System::arraycopy(groups, 0, expandedGroups, 0, before);
				// Copy groups after the gap
				System::arraycopy(groups, gapPos + 1, expandedGroups, 8 - after, after);
			} else{
				// No gap found, copy all groups
				System::arraycopy(groups, 0, expandedGroups, 0, groups.length);
			}
			// Parse each group
			ip.msb=0;
			ip.lsb=0;
			for(int32_t i=0;i < 8;i++){
				if(expandedGroups[i].isEmpty()){
					continue;
				}
				int32_t group=parseInt(expandedGroups[i], 16);
				if(i < 4){
					ip.msb|=((int64_t)group << (48 - 16 * i));
				} else{
					ip.lsb|=((int64_t)group << (112 - 16 * i));
				}
			}
		}
		if(parts.length > 1){
			ip.maskLength=parseInt(parts[1]);
			if(ip.maskLength < 0 || ip.maskLength>128){
				throw IllegalArgumentException("Invalid IPv6 mask length");
			}
		} else{
			ip.maskLength=128;
		}
		return ipptr;
	}

	int32_t IP6Address::hashCode() const{
		return Arrays::hashCode(msb, lsb, maskLength);
	}

	bool IP6Address::operator==(const IP6Address & that) const{
		return msb == that.msb && lsb == that.lsb && maskLength == that.maskLength;
	}

	bool IP6Address::inRange(const IPAddress * targetRange) const{
		if(!IPAddress::isIPV6(targetRange)) return false;
		const IP6Address * target=static_cast<const IP6Address *>(targetRange);
		if(target == nullptr) return false;

		if(target->maskLength <= 64){
			// 只需要比较高位部分
			int64_t mask=~((1LL << (64 - target->maskLength)) - 1);
			return (this->msb & mask) == (target->msb & mask);
		} else{
			// 需要比较高位和部分低位
			if(this->msb != target->msb){
				return false;
			}
			int64_t mask=~((1LL << (128 - target->maskLength)) - 1);
			return (this->lsb & mask) == (target->lsb & mask);
		}
	}

	String IP6Address::toFullString() const{
		return StringFormat::format("%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x%s",
									static_cast<int32_t>((msb >> 48) & 0xffff),
									static_cast<int32_t>((msb >> 32) & 0xffff),
									static_cast<int32_t>((msb >> 16) & 0xffff),
									static_cast<int32_t>(msb & 0xffff),
									static_cast<int32_t>((lsb >> 48) & 0xffff),
									static_cast<int32_t>((lsb >> 32) & 0xffff),
									static_cast<int32_t>((lsb >> 16) & 0xffff),
									static_cast<int32_t>(lsb & 0xffff),
									maskLength != 128?String("/") + maskLength:""
		);
	}

	String IP6Address::toMaskedString() const{
		int64_t maskMsb=maskLength > 64?~0LL:~((1LL << (64 - maskLength)) - 1);
		int64_t maskLsb=maskLength <= 64?0:~((1LL << (128 - maskLength)) - 1);
		int64_t netMsb=msb & maskMsb;
		int64_t netLsb=lsb & maskLsb;

		return StringFormat::format("%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
									static_cast<int32_t>((netMsb >> 48) & 0xffff),
									static_cast<int32_t>((netMsb >> 32) & 0xffff),
									static_cast<int32_t>((netMsb >> 16) & 0xffff),
									static_cast<int32_t>(netMsb & 0xffff),
									static_cast<int32_t>((netLsb >> 48) & 0xffff),
									static_cast<int32_t>((netLsb >> 32) & 0xffff),
									static_cast<int32_t>((netLsb >> 16) & 0xffff),
									static_cast<int32_t>(netLsb & 0xffff)
		);
	}

	std::shared_ptr<IPAddress> IP6Address::toMasked(int32_t maskLength) const{
		int64_t maskMsb=maskLength > 64?~0LL:~((1LL << (64 - maskLength)) - 1);
		int64_t maskLsb=maskLength <= 64?0:~((1LL << (128 - maskLength)) - 1);
		int64_t netMsb=msb & maskMsb;
		int64_t netLsb=lsb & maskLsb;
		return std::make_shared<IP6Address>(maskLength, netMsb, netLsb);
	}

	std::shared_ptr<IPAddress> IP6Address::clone() const{
		auto a=toByte();
		return std::make_shared<IP6Address>(*a);
	}

	std::shared_ptr<ByteArray> IP6Address::toByte() const{
		std::shared_ptr<ByteArray> bptr=std::make_shared<ByteArray>(20); // BE: ip6 mask
		ByteArray & b=*bptr;

		// 写入高64位 (msb)
		b[0]=static_cast<int8_t>((msb >> 56) & 0xff);
		b[1]=static_cast<int8_t>((msb >> 48) & 0xff);
		b[2]=static_cast<int8_t>((msb >> 40) & 0xff);
		b[3]=static_cast<int8_t>((msb >> 32) & 0xff);
		b[4]=static_cast<int8_t>((msb >> 24) & 0xff);
		b[5]=static_cast<int8_t>((msb >> 16) & 0xff);
		b[6]=static_cast<int8_t>((msb >> 8) & 0xff);
		b[7]=static_cast<int8_t>(msb & 0xff);

		// 写入低64位 (lsb)
		b[8]=static_cast<int8_t>((lsb >> 56) & 0xff);
		b[9]=static_cast<int8_t>((lsb >> 48) & 0xff);
		b[10]=static_cast<int8_t>((lsb >> 40) & 0xff);
		b[11]=static_cast<int8_t>((lsb >> 32) & 0xff);
		b[12]=static_cast<int8_t>((lsb >> 24) & 0xff);
		b[13]=static_cast<int8_t>((lsb >> 16) & 0xff);
		b[14]=static_cast<int8_t>((lsb >> 8) & 0xff);
		b[15]=static_cast<int8_t>(lsb & 0xff);

		// 写入掩码长度
		b[16]=static_cast<int8_t>((maskLength >> 24) & 0xff);
		b[17]=static_cast<int8_t>((maskLength >> 16) & 0xff);
		b[18]=static_cast<int8_t>((maskLength >> 8) & 0xff);
		b[19]=static_cast<int8_t>(maskLength & 0xff);

		return bptr;
	}

	void IP6Address::fromByte(const ByteArray & b){
		// 读取高64位 (msb)
		msb=(static_cast<int64_t>(b[0] & 0xff) << 56) |
			(static_cast<int64_t>(b[1] & 0xff) << 48) |
			(static_cast<int64_t>(b[2] & 0xff) << 40) |
			(static_cast<int64_t>(b[3] & 0xff) << 32) |
			(static_cast<int64_t>(b[4] & 0xff) << 24) |
			(static_cast<int64_t>(b[5] & 0xff) << 16) |
			(static_cast<int64_t>(b[6] & 0xff) << 8) |
			(static_cast<int64_t>(b[7] & 0xff));

	  // 读取低64位 (lsb)
		lsb=(static_cast<int64_t>(b[8] & 0xff) << 56) |
			(static_cast<int64_t>(b[9] & 0xff) << 48) |
			(static_cast<int64_t>(b[10] & 0xff) << 40) |
			(static_cast<int64_t>(b[11] & 0xff) << 32) |
			(static_cast<int64_t>(b[12] & 0xff) << 24) |
			(static_cast<int64_t>(b[13] & 0xff) << 16) |
			(static_cast<int64_t>(b[14] & 0xff) << 8) |
			(static_cast<int64_t>(b[15] & 0xff));

	  // 读取掩码长度
		maskLength=((b[16] & 0xff) << 24) |
			((b[17] & 0xff) << 16) |
			((b[18] & 0xff) << 8) |
			((b[19] & 0xff));
	}

	String IP6Address::toSimpleString() const{
		// 直接处理特殊情况
		if(msb == 0 && lsb == 1) return "::1";
		if(msb == 0 && lsb == 0) return "::";
		// 将地址分为8个16位组
		IntArray groups(8);
		groups[0]=(int)((msb >> 48) & 0xffff);
		groups[1]=(int)((msb >> 32) & 0xffff);
		groups[2]=(int)((msb >> 16) & 0xffff);
		groups[3]=(int)(msb & 0xffff);
		groups[4]=(int)((lsb >> 48) & 0xffff);
		groups[5]=(int)((lsb >> 32) & 0xffff);
		groups[6]=(int)((lsb >> 16) & 0xffff);
		groups[7]=(int)(lsb & 0xffff);
		// 找出最长的连续0段
		int bestStart=-1, bestLen=0;
		int currentStart=-1, currentLen=0;
		for(int i=0;i <= groups.length;i++){
			if(i < groups.length && groups[i] == 0){
				if(currentStart == -1) currentStart=i;
				currentLen++;
			} else{
				if(currentLen > bestLen){
					bestLen=currentLen;
					bestStart=currentStart;
				}
				currentStart=-1;
				currentLen=0;
			}
		}
		// 构建简化字符串
		StringBuilder sb;
		for(int i=0;i < groups.length;){
			if(i == bestStart && bestLen > 1){
				sb.append("::");
				i+=bestLen;
			} else{
				// 输出非零组（去掉前导零）
				if(groups[i] != 0){
					sb.append(toHexString(groups[i]));
				} else{
					sb.append("0");
				}
				i++;
				if(i < groups.length && i != bestStart){
					sb.append(":");
				}
			}
		}
		return sb.toString();
	}
	int IP6Address::getVersion()const{ return 6; }
}